---
title: Issuer
editUrl: https://github.com/toolbeam/openauth/blob/master/packages/openauth/src/issuer.ts
description: Reference doc for the OpenAuth server.
---

import { Segment, Section, NestedTitle, InlineSection } from 'toolbeam-docs-theme/components'
import { Tabs, TabItem } from '@astrojs/starlight/components'

<div class="tsdoc">
<Section type="about">
The `issuer` create an OpentAuth server, a [Hono](https://hono.dev) app that's
designed to run anywhere.

The `issuer` function requires a few things:

```ts title="issuer.ts"
import { issuer } from "@openauthjs/openauth"

const app = issuer({
  providers: { ... },
  storage,
  subjects,
  success: async (ctx, value) => { ... }
})
```

#### Add providers

You start by specifying the auth providers you are going to use. Let's say you want your users
to be able to authenticate with GitHub and with their email and password.

```ts title="issuer.ts"
import { GithubProvider } from "@openauthjs/openauth/provider/github"
import { PasswordProvider } from "@openauthjs/openauth/provider/password"

const app = issuer({
  providers: {
    github: GithubProvider({
      // ...
    }),
    password: PasswordProvider({
      // ...
    }),
  },
})
```

#### Handle success

The `success` callback receives the payload when a user completes a provider's auth flow.

```ts title="issuer.ts"
const app = issuer({
  providers: { ... },
  subjects,
  async success(ctx, value) {
    let userID
    if (value.provider === "password") {
      console.log(value.email)
      userID = ... // lookup user or create them
    }
    if (value.provider === "github") {
      console.log(value.tokenset.access)
      userID = ... // lookup user or create them
    }
    return ctx.subject("user", {
      userID
    })
  }
})
```

Once complete, the `issuer` issues the access tokens that a client can use. The `ctx.subject`
call is what is placed in the access token as a JWT.

#### Define subjects

You define the shape of these in the `subjects` field.

```ts title="subjects.ts"
import { object, string } from "valibot"
import { createSubjects } from "@openauthjs/openauth/subject"

const subjects = createSubjects({
  user: object({
    userID: string()
  })
})
```

It's good to place this in a separate file since this'll be used in your client apps as well.

```ts title="issuer.ts"
import { subjects } from "./subjects.js"

const app = issuer({
  providers: { ... },
  subjects,
  // ...
})
```

#### Deploy

Since `issuer` is a Hono app, you can deploy it anywhere Hono supports.

<Tabs>
  <TabItem label="Node">
  ```ts title="issuer.ts"
  import { serve } from "@hono/node-server"

  serve(app)
  ```
  </TabItem>
  <TabItem label="Lambda">
  ```ts title="issuer.ts"
  import { handle } from "hono/aws-lambda"

  export const handler = handle(app)
  ```
  </TabItem>
  <TabItem label="Bun">
  ```ts title="issuer.ts"
  export default app
  ```
  </TabItem>
  <TabItem label="Workers">
  ```ts title="issuer.ts"
  export default app
  ```
  </TabItem>
</Tabs>
</Section>
---
## Methods
### issuer
<Segment>
<Section type="signature">
```ts
issuer(input)
```
</Section>
<Section type="parameters">
#### Parameters
- <p><code class="key">input</code> [<code class="type">IssuerInput</code>](#issuerinput)</p>
</Section>
<InlineSection>
**Returns** <code class="type">Hono</code>
</InlineSection>
Create an OpenAuth server, a Hono app.
</Segment>
## IssuerInput
<Segment>
<Section type="parameters">
- <p>[<code class="key">providers</code>](#issuerinput.providers) <code class="primitive">Record</code><code class="symbol">&lt;</code><code class="primitive">string</code>, <code class="type">Provider</code><code class="symbol">&gt;</code></p>
- <p>[<code class="key">storage?</code>](#issuerinput.storage) <code class="type">StorageAdapter</code></p>
- <p>[<code class="key">subjects</code>](#issuerinput.subjects) [<code class="type">SubjectSchema</code>](/docs/subject#subjectschema)</p>
- <p>[<code class="key">theme?</code>](#issuerinput.theme) [<code class="type">Theme</code>](#theme)</p>
- <p>[<code class="key">ttl?</code>](#issuerinput.ttl) <code class="primitive">Object</code></p>
  - <p>[<code class="key">access?</code>](#ttl.access) <code class="primitive">number</code></p>
  - <p>[<code class="key">refresh?</code>](#ttl.refresh) <code class="primitive">number</code></p>
  - <p>[<code class="key">retention?</code>](#ttl.retention) <code class="primitive">number</code></p>
  - <p>[<code class="key">reuse?</code>](#ttl.reuse) <code class="primitive">number</code></p>
- <p>[<code class="key">allow?</code>](#issuerinput.allow) <code class="primitive">(input: <code class="symbol">&lcub; </code><code class="key">audience</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">clientID</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">redirectURI</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol"> &rcub;</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="primitive">boolean</code><code class="symbol">&gt;</code></code></p>
- <p>[<code class="key">select?</code>](#issuerinput.select) <code class="primitive">(providers: <code class="primitive">Record</code><code class="symbol">&lt;</code><code class="primitive">string</code>, <code class="primitive">string</code><code class="symbol">&gt;</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code></p>
- <p>[<code class="key">success</code>](#issuerinput.success) <code class="primitive">(response: [<code class="type">OnSuccessResponder</code>](#onsuccessresponder), input: <code class="type">Result</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code></p>
</Section>
</Segment>
<NestedTitle id="issuerinput.providers" Tag="h4" parent="IssuerInput.">providers</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">Record</code><code class="symbol">&lt;</code><code class="primitive">string</code>, <code class="type">Provider</code><code class="symbol">&gt;</code>
</InlineSection>
</Section>
The providers that you want your OpenAuth server to support.
```ts title="issuer.ts"
import { GithubProvider } from "@openauthjs/openauth/provider/github"

issuer({
  providers: {
    github: GithubProvider()
  }
})
```


The key is just a string that you can use to identify the provider. It's passed back to
the 
`success`
 callback.

You can also specify multiple providers.


```ts
{
  providers: {
    github: GithubProvider(),
    google: GoogleProvider()
  }
}
```
</Segment>
<NestedTitle id="issuerinput.storage" Tag="h4" parent="IssuerInput.">storage?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="type">StorageAdapter</code>
</InlineSection>
</Section>
The storage adapter that you want to use.
```ts title="issuer.ts"
import { DynamoStorage } from "@openauthjs/openauth/storage/dynamo"

issuer({
  storage: DynamoStorage()
  // ...
})
```
</Segment>
<NestedTitle id="issuerinput.subjects" Tag="h4" parent="IssuerInput.">subjects</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** [<code class="type">SubjectSchema</code>](/docs/subject#subjectschema)
</InlineSection>
</Section>
The shape of the subjects that you want to return.
```ts title="issuer.ts"
import { object, string } from "valibot"
import { createSubjects } from "@openauthjs/openauth/subject"

issuer({
  subjects: createSubjects({
    user: object({
      userID: string()
    })
  })
  // ...
})
```
</Segment>
<NestedTitle id="issuerinput.theme" Tag="h4" parent="IssuerInput.">theme?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** [<code class="type">Theme</code>](#theme)
</InlineSection>
</Section>
The theme you want to use for the UI.

This includes the UI the user sees when selecting a provider. And the `PasswordUI` and
`CodeUI` that are used by the `PasswordProvider` and `CodeProvider`.
```ts title="issuer.ts"
import { THEME_SST } from "@openauthjs/openauth/ui/theme"

issuer({
  theme: THEME_SST
  // ...
})
```


Or define your own.


```ts title="issuer.ts"
import type { Theme } from "@openauthjs/openauth/ui/theme"

const MY_THEME: Theme = {
  // ...
}

issuer({
  theme: MY_THEME
  // ...
})
```
</Segment>
<NestedTitle id="issuerinput.ttl" Tag="h4" parent="IssuerInput.">ttl?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">Object</code>
</InlineSection>
</Section>
Set the TTL, in seconds, for access and refresh tokens.
```ts
{
  ttl: {
    access: 60 * 60 * 24 * 30,
    refresh: 60 * 60 * 24 * 365
  }
}
```
</Segment>
<NestedTitle id="ttl.access" Tag="h5" parent="IssuerInput.ttl.">access?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">number</code>
</InlineSection>
</Section>

<InlineSection>
**Default** 30d
</InlineSection>
Interval in seconds where the access token is valid.
</Segment>
<NestedTitle id="ttl.refresh" Tag="h5" parent="IssuerInput.ttl.">refresh?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">number</code>
</InlineSection>
</Section>

<InlineSection>
**Default** 1y
</InlineSection>
Interval in seconds where the refresh token is valid.
</Segment>
<NestedTitle id="ttl.retention" Tag="h5" parent="IssuerInput.ttl.">retention?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">number</code>
</InlineSection>
</Section>

<InlineSection>
**Default** 0s
</InlineSection>
Interval in seconds to retain refresh tokens for reuse detection.
</Segment>
<NestedTitle id="ttl.reuse" Tag="h5" parent="IssuerInput.ttl.">reuse?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">number</code>
</InlineSection>
</Section>

<InlineSection>
**Default** 60s
</InlineSection>
Interval in seconds where refresh token reuse is allowed. This helps mitigrate
concurrency issues.
</Segment>
<NestedTitle id="issuerinput.allow" Tag="h4" parent="IssuerInput.">allow?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">(input: <code class="symbol">&lcub; </code><code class="key">audience</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">clientID</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">redirectURI</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol"> &rcub;</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="primitive">boolean</code><code class="symbol">&gt;</code></code>
</InlineSection>
</Section>
Override the logic for whether a client request is allowed to call the issuer.

By default, it uses the following:

- Allow if the `redirectURI` is localhost.
- Compare `redirectURI` to the request's hostname or the `x-forwarded-host` header. If they
  are from the same sub-domain level, then allow.
```ts
{
  allow: async (input, req) => {
    // Allow all clients
    return true
  }
}
```
</Segment>
<NestedTitle id="issuerinput.select" Tag="h4" parent="IssuerInput.">select?</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">(providers: <code class="primitive">Record</code><code class="symbol">&lt;</code><code class="primitive">string</code>, <code class="primitive">string</code><code class="symbol">&gt;</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code>
</InlineSection>
</Section>

<InlineSection>
**Default** Select()
</InlineSection>
Optionally, configure the UI that's displayed when the user visits the root URL of the
of the OpenAuth server.

```ts title="issuer.ts"
import { Select } from "@openauthjs/openauth/ui/select"

issuer({
  select: Select({
    providers: {
      github: { hide: true },
      google: { display: "Google" }
    }
  })
  // ...
})
```
</Segment>
<NestedTitle id="issuerinput.success" Tag="h4" parent="IssuerInput.">success</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">(response: [<code class="type">OnSuccessResponder</code>](#onsuccessresponder), input: <code class="type">Result</code>, req: <code class="type">Request</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code>
</InlineSection>
</Section>
The success callback that's called when the user completes the flow.

This is called after the user has been redirected back to your app after the OAuth flow.
```ts
{
  success: async (ctx, value) => {
    let userID
    if (value.provider === "password") {
      console.log(value.email)
      userID = ... // lookup user or create them
    }
    if (value.provider === "github") {
      console.log(value.tokenset.access)
      userID = ... // lookup user or create them
    }
    return ctx.subject("user", {
      userID
    })
  },
  // ...
}
```
</Segment>
## OnSuccessResponder
<Segment>
<Section type="parameters">
- <p>[<code class="key">subject</code>](#onsuccessresponder.subject) <code class="primitive">(type: <code class="primitive">string</code>, properties: <code class="primitive">any</code>, opts?: <code class="symbol">&lcub; </code><code class="key">subject</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">ttl</code><code class="symbol">&colon; </code><code class="symbol">&lcub; </code><code class="key">access</code><code class="symbol">&colon; </code><code class="primitive">number</code><code class="symbol">, </code><code class="key">refresh</code><code class="symbol">&colon; </code><code class="primitive">number</code><code class="symbol"> &rcub;</code><code class="symbol"> &rcub;</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code></p>
</Section>
Sets the subject payload in the JWT token and returns the response.

```ts
ctx.subject("user", {
  userID
})
```
</Segment>
<NestedTitle id="onsuccessresponder.subject" Tag="h4" parent="OnSuccessResponder.">subject</NestedTitle>
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">(type: <code class="primitive">string</code>, properties: <code class="primitive">any</code>, opts?: <code class="symbol">&lcub; </code><code class="key">subject</code><code class="symbol">&colon; </code><code class="primitive">string</code><code class="symbol">, </code><code class="key">ttl</code><code class="symbol">&colon; </code><code class="symbol">&lcub; </code><code class="key">access</code><code class="symbol">&colon; </code><code class="primitive">number</code><code class="symbol">, </code><code class="key">refresh</code><code class="symbol">&colon; </code><code class="primitive">number</code><code class="symbol"> &rcub;</code><code class="symbol"> &rcub;</code>) => <code class="primitive">Promise</code><code class="symbol">&lt;</code><code class="type">Response</code><code class="symbol">&gt;</code></code>
</InlineSection>
</Section>
The `type` is the type of the subject, that was defined in the `subjects` field.

The `properties` are the properties of the subject. This is the shape of the subject that
you defined in the `subjects` field.
</Segment>
## Errors
<Section type="about">
A list of errors that can be thrown by OpenAuth.

You can use these errors to check the type of error and handle it. For example.

```ts
import { InvalidAuthorizationCodeError } from "@openauthjs/openauth/error"

if (err instanceof InvalidAuthorizationCodeError) {
  // handle invalid code error
}
```
</Section>
---
### InvalidAccessTokenError
<Segment>
The given access token is invalid.
</Segment>
### InvalidAuthorizationCodeError
<Segment>
The given authorization code is invalid.
</Segment>
### InvalidRefreshTokenError
<Segment>
The given refresh token is invalid.
</Segment>
### InvalidSubjectError
<Segment>
The given subject is invalid.
</Segment>
### MissingParameterError
<Segment>
The given parameter is missing.
</Segment>
### MissingProviderError
<Segment>
The `provider` needs to be passed in.
</Segment>
### OauthError
<Segment>
The OAuth server returned an error.
</Segment>
### UnauthorizedClientError
<Segment>
The given client is not authorized to use the redirect URI that was passed in.
</Segment>
### UnknownStateError
<Segment>
The browser was in an unknown state.

This can happen when certain cookies have expired. Or the browser was switched in the middle
of the authentication flow.
</Segment>
</div>